home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / rings.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  7.0 KB  |  221 lines  |  [TEXT/R*ch]

  1. /*
  2.  * rings.c - Create objects with 6 pentagonal rings which connect the midpoints
  3.  *    of the edges of a dodecahedron.  A pyramid of these objects is formed,
  4.  *    which the viewer looks upon from the point.  A plane is placed behind
  5.  *    the pyramid for shadows.  Three light sources.
  6.  *
  7.  * Author:  Eric Haines, 3D/Eye, Inc.
  8.  *
  9.  * size_factor determines the number of objects output.
  10.  *    Each object has 30 cylinders and 30 spheres.
  11.  *    Total objects = SF*SF + (SF-1)*(SF-1) + ... + 1 plus 1 backdrop square.
  12.  *    formula for # of spheres or cylinders = 5*SF*(SF+1)*(2*SF+1)
  13.  *
  14.  *    size_factor    # spheres    # cylinders    # squares
  15.  *         1            30              30         1
  16.  *         2           150             150         1
  17.  *         3           420             420         1
  18.  *
  19.  *         7          4200            4200         1
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <stdlib.h>    /* atoi */
  25. #include "def.h"
  26. #include "drv.h"    /* display_close() */
  27. #include "lib.h"
  28.  
  29. static int size_factor = 7 ;
  30. static int raytracer_format = OUTPUT_RT_DEFAULT;
  31. static int output_format    = OUTPUT_CURVES;
  32.  
  33. #ifdef OUTPUT_TO_FILE
  34. static FILE * stdout_file = NULL;
  35. #else
  36. #define stdout_file stdout
  37. #endif /* OUTPUT_TO_FILE */
  38.  
  39. /* if spread out is > 1, succeeding layers spread out more */
  40. #define    SPREAD_OUT        1
  41.  
  42. /* Create the set of 30 points needed to generate the rings */
  43. void
  44. create_dodec( minor_radius, vertex )
  45.     double minor_radius ;
  46.     COORD3 vertex[30] ;
  47. {
  48.     int num_vertex, num_pentagon ;
  49.     double scale, x_rotation, z_rotation ;
  50.     COORD3 temp_vertex ;
  51.     MATRIX x_matrix, z_matrix ;
  52.  
  53.     /* scale object to fit in a sphere of radius 1 */
  54.     scale = 1.0 / ( 1.0 + minor_radius ) ;
  55.  
  56.     /*
  57.      * define one pentagon as on the XY plane, with points starting along +X
  58.      * and N fifths of the way around the Z axis.
  59.      */
  60.     for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) {
  61.     vertex[num_vertex][X] = scale * cos((double)num_vertex * 2.0*PI/5.0 ) ;
  62.     vertex[num_vertex][Y] = scale * sin((double)num_vertex * 2.0*PI/5.0 ) ;
  63.     vertex[num_vertex][Z] = 0.0 ;
  64.     vertex[num_vertex][W] = 1.0 ;
  65.     }
  66.  
  67.     /*
  68.      * find the rotation angle (in radians) along the X axis:
  69.      * angle between two adjacent dodecahedron faces.
  70.      */
  71.     x_rotation = 2.0 *
  72.         acos( cos( (double)(PI/3.0) ) / sin( (double)(PI/5.0) ) ) ;
  73.     lib_create_rotate_matrix( x_matrix, X_AXIS, x_rotation ) ;
  74.  
  75.     /*
  76.      * Find each of the other 5 pentagons:  rotate along the X axis,
  77.      * then rotate on the Z axis.
  78.      */
  79.     for ( num_pentagon = 1 ; num_pentagon < 6 ; ++num_pentagon ) {
  80.     /*
  81.      * find the rotation angle (in radians) along the Z axis:
  82.      * 1/10th plus N fifths of the way around * 2 * PI.
  83.      */
  84.     z_rotation = PI*( 2.0*(double)(num_pentagon-1)+1.0 ) / 5.0 ;
  85.     lib_create_rotate_matrix( z_matrix, Z_AXIS, z_rotation ) ;
  86.  
  87.     for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) {
  88.  
  89.         lib_transform_point( temp_vertex
  90.                    , vertex[num_vertex]
  91.                    , x_matrix
  92.                    ) ;
  93.  
  94.         lib_transform_point( vertex[5*num_pentagon+num_vertex]
  95.                    , temp_vertex
  96.                    , z_matrix
  97.                    ) ;
  98.     }
  99.     }
  100. }
  101.  
  102. int
  103. main(argc,argv)
  104.     int argc;
  105.     char *argv[];
  106. {
  107.     int    prev_elem, num_elem, num_depth, num_objx, num_objz ;
  108.     double radius, spread, y_diff, xz_diff ;
  109.     COORD4 base_pt, apex_pt ;
  110.     COORD3 from, at, up ;
  111.     COORD3 wvec, light ;
  112.     COORD3 back_color, ring_color[6] ;
  113.     COORD3 wall[4], offset, dodec[30] ;
  114.     double lscale;
  115.  
  116.     PLATFORM_INIT(SPD_RINGS);
  117.  
  118.     /* Start by defining which raytracer we will be using */
  119.      if ( lib_gen_get_opts( argc, argv,
  120.             &size_factor, &raytracer_format, &output_format ) ) {
  121.     return EXIT_FAIL;
  122.     }
  123.     if ( lib_open( raytracer_format, "Rings.out" ) ) {
  124.     return EXIT_FAIL;
  125.     }
  126.  
  127.     radius = 0.07412 ;    /* cone and sphere radius */
  128.  
  129.     /* calculate spread of objects */
  130.     spread = 1 / sin( (double)( PI/8.0 ) ) ;
  131.     if ( SPREAD_OUT <= spread ) {
  132.     y_diff = spread / SPREAD_OUT ;
  133.     xz_diff = 1.0 ;
  134.     }
  135.     else {
  136.     y_diff = 1.0 ;
  137.     xz_diff = SPREAD_OUT / spread ;
  138.     }
  139.  
  140.     /* output background color - UNC sky blue */
  141.     /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */
  142.     /* note that the background color should never be seen */
  143.     SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
  144.     lib_output_background_color( back_color ) ;
  145.  
  146.     /* output viewpoint */
  147.     SET_COORD3( from, -1.0, -spread, 0.5 ) ;
  148.     SET_COORD3( at, from[X], from[Y] + 1.0, from[Z] ) ;
  149.     SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
  150.     lib_output_viewpoint( from, at, up, 45.0, 1.0, 1.0, 512, 512);
  151.  
  152.     /* output light source */
  153.     lscale = (raytracer_format == OUTPUT_NFF ||
  154.           raytracer_format == OUTPUT_RTRACE ? 1.0 : 1.0/sqrt(3.0));
  155.     SET_COORD4( light, 3.0, -spread, 3.0, lscale ) ;
  156.     lib_output_light( light ) ;
  157.     SET_COORD4( light, -4.0, -spread, 1.0, lscale ) ;
  158.     lib_output_light( light ) ;
  159.     SET_COORD4( light, 2.0, -spread, -4.0, lscale ) ;
  160.     lib_output_light( light ) ;
  161.  
  162.     /* output wall polygon - white */
  163.     SET_COORD3( back_color, 1.0, 1.0, 1.0 ) ;
  164.     lib_output_color(NULL, back_color, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  165.  
  166.     /* just spans 45 degree view + 1% */
  167.     wvec[Y] = y_diff * ( size_factor + 1 ) ;
  168.     wvec[X] = wvec[Z] = 1.01 * ( wvec[Y] - from[Y] ) * tan( PI / 8.0 ) ;
  169.     SET_COORD3( wall[0],  wvec[X]+from[X], wvec[Y],  wvec[Z]+from[Z] ) ;
  170.     SET_COORD3( wall[1], -wvec[X]+from[X], wvec[Y],  wvec[Z]+from[Z] ) ;
  171.     SET_COORD3( wall[2], -wvec[X]+from[X], wvec[Y], -wvec[Z]+from[Z] ) ;
  172.     SET_COORD3( wall[3],  wvec[X]+from[X], wvec[Y], -wvec[Z]+from[Z] ) ;
  173.     lib_output_polygon( 4, wall ) ;
  174.  
  175.     /* set up ring colors - RGB and complements */
  176.     SET_COORD3( ring_color[0], 1.0, 0.0, 0.0 ) ;
  177.     SET_COORD3( ring_color[1], 0.0, 1.0, 0.0 ) ;
  178.     SET_COORD3( ring_color[2], 0.0, 0.0, 1.0 ) ;
  179.     SET_COORD3( ring_color[3], 0.0, 1.0, 1.0 ) ;
  180.     SET_COORD3( ring_color[4], 1.0, 0.0, 1.0 ) ;
  181.     SET_COORD3( ring_color[5], 1.0, 1.0, 0.0 ) ;
  182.  
  183.     create_dodec( radius, dodec ) ;
  184.     /* radius of osculating cylinders and spheres (no derivation given) */
  185.     base_pt[W] = apex_pt[W] = radius ;
  186.  
  187.     for ( num_depth = 0 ; num_depth < size_factor ; ++num_depth ) {
  188.     offset[Y] = y_diff * (double)(num_depth+1) ;
  189.     for ( num_objz = 0 ; num_objz <= num_depth ; ++num_objz ) {
  190.         offset[Z] = xz_diff * (double)(2*num_objz - num_depth) ;
  191.         for ( num_objx = 0 ; num_objx <= num_depth ; ++num_objx ) {
  192.         offset[X] = xz_diff * (double)(2*num_objx - num_depth) ;
  193.         for ( num_elem = 0 ; num_elem < 30 ; ++num_elem ) {
  194.             PLATFORM_MULTITASK();
  195.             COPY_COORD3( base_pt, dodec[num_elem] ) ;
  196.             ADD2_COORD3( base_pt, offset ) ;
  197.             if ( num_elem%5 == 0 ) {
  198.             prev_elem = num_elem + 4 ;
  199.             /* new ring beginning - output color */
  200.             lib_output_color(NULL, ring_color[num_elem/5],
  201.                      0.0, 0.5, 0.2, 0.3, 10.0, 0.0, 0.0);
  202.             }
  203.             else {
  204.             prev_elem = num_elem - 1 ;
  205.             }
  206.             COPY_COORD3( apex_pt, dodec[prev_elem] ) ;
  207.             ADD2_COORD3( apex_pt, offset ) ;
  208.  
  209.             lib_output_cylcone( base_pt, apex_pt, output_format ) ;
  210.             lib_output_sphere( base_pt, output_format ) ;
  211.         }
  212.         }
  213.     }
  214.     }
  215.  
  216.     lib_close();
  217.  
  218.     PLATFORM_SHUTDOWN();
  219.     return EXIT_SUCCESS;
  220. }
  221.